#!/usr/bin/env python
#-*- coding: utf-8 -*-
import tornado.web
import tornado.websocket
import tornado.httpserver
import tornado.ioloop
import tornado.gen
import signal
import threading
import MySQLdb
import traceback
import json

from chatroom.cache import get_cache
from wetalk.models import Room, Message

def connect_db():
    return MySQLdb.connect(db='chatroom', host='localhost', user='root', passwd='123456')


class RoomChannelHandler(tornado.websocket.WebSocketHandler):
    def check_origin(self, origin):
        return True

    def open(self, room_id):
        if Room.objects.filter(id=room_id).count() == 0:
            self.close(404)
            return
        self.room_id = int(room_id)
        cache = get_cache(use_pool=True)
        key = 'memberCount:%d' % (self.room_id, )
        cache.incr(key)
        if roomMembers.get(self.room_id) == None:
            roomMembers[self.room_id] = []
        roomMembers[self.room_id].append(self)

    def on_message(self, message):
        cache = get_cache(use_pool=True)
        key = 'roomChannel:%d' % (self.room_id, )
        try:
            message = json.loads(message)
        except:
            return
        if message['type'] == 'sendmsg' and len(message.get('data')) > 0:
            data = message['data']
            nickname, content = data['nickname'], data['content']
            data['id'] = Message.objects.create(room_id=self.room_id, nickname=nickname, content=content).id
            cache.publish(key, json.dumps(data))

    def on_close(self):
        cache = get_cache(use_pool=True)
        key = 'memberCount:%d' % (self.room_id, )
        roomMembers[self.room_id].remove(self)
        cache.decr(key)


class Application(tornado.web.Application):
    def __init__(self):
        handlers = [
            (r'/rt/room/([1-9][0-9]*)', RoomChannelHandler),
        ]

        tornado.web.Application.__init__(self, handlers)


def reduceMember():
    cache = get_cache(use_pool=True)
    for room_id in roomMembers:
        remaining_count = len(roomMembers[room_id])
        if remaining_count > 0:
            key = 'memberCount:%d' % (room_id, )
            cache.decr(key, remaining_count)
    tornado.ioloop.IOLoop.instance().stop()


roomMembers = {}
def distributor():
    p = get_cache(use_pool=True).pubsub()
    p.psubscribe('roomChannel:*')
    try:
        while True:
            message = p.get_message()
            if message and message['type'] == 'pmessage':
                channel_name = message['channel']
                room_id = int(channel_name[channel_name.find(':')+1:])
                data = json.dumps({'type': 'recvmsg', 'data': message['data']})
                for con in roomMembers.get(room_id, []):
                    try:
                        con.write_message(data)
                    except Exception, e:
                        traceback.print_exc()
    except Exception, e:
        traceback.print_exc()


def run():
    app = Application()
    server = tornado.httpserver.HTTPServer(app)
    server.listen(10001)
    instance = tornado.ioloop.IOLoop.instance()
    signal.signal(signal.SIGINT, lambda sig, frame: instance.add_callback_from_signal(reduceMember))

    t = threading.Thread(target=distributor)
    t.setDaemon(True)
    t.start()

    instance.start()

